package com.frame.sentinel.resource;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.env.EnvironmentPostProcessor;
import org.springframework.core.env.ConfigurableEnvironment;
import org.springframework.core.env.PropertiesPropertySource;
import org.springframework.core.env.PropertySource;
import org.springframework.core.io.ClassPathResource;
import org.springframework.core.io.FileSystemResource;
import org.springframework.core.io.Resource;
import org.springframework.core.io.support.PropertiesLoaderUtils;
import org.springframework.stereotype.Component;
import org.springframework.util.ResourceUtils;
import org.springframework.util.StringUtils;

import java.io.File;
import java.io.IOException;
import java.util.*;

/**
 * @auther zhangwj
 * @date 2021/4/9 下午3:18
 */
@Component
public class ProfileEnvironmentPostProcessor implements EnvironmentPostProcessor {

    private static final String DEFAULT_PROFILES = "classpath:application.properties";

    private static final String SPRING_PROFILES_ACTIVE = "spring.profiles.active";

    private static final String SENTINEL_SCOPE = "sentinel.scope";


    private static final String DEFAULT_PROFILES_1 = "classpath:application-{active}.properties";


    @Override
    public void postProcessEnvironment(ConfigurableEnvironment environment, SpringApplication application) {
        List<String> sentinelScope = new ArrayList<>();
        try {
            File file = ResourceUtils.getFile(DEFAULT_PROFILES);
            Properties properties = loadProperties(file);
            String scope = properties.getProperty(SENTINEL_SCOPE);
            if (StringUtils.isEmpty(scope)) {
                String active = properties.getProperty(SPRING_PROFILES_ACTIVE);
                if (StringUtils.isEmpty(active)) {
                    return;
                } else {
                    file = ResourceUtils.getFile(DEFAULT_PROFILES_1.replace("{active}", active));
                    properties = loadProperties(file);
                    scope = properties.getProperty(SENTINEL_SCOPE);
                    if (StringUtils.isEmpty(scope)) {
                        return;
                    }
                }
            }
            if (!StringUtils.isEmpty(scope)) {
                String[] scopes = scope.split(",");
                sentinelScope.addAll(Arrays.asList(scopes));
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
        if (sentinelScope.isEmpty()) {
            throw new NullPointerException("资源目录为空");
        }
        if (!sentinelScope.contains("main")) {
            throw new IllegalArgumentException("不包含主资源");
        }
        Map<String, String> pathMap = new HashMap<>();
        pathMap.put("main", "sentinel.properties");
        pathMap.put("flow", "sentinel-flow.properties");
        pathMap.put("gw_flow", "sentinel-gateway-flow.properties");
        pathMap.put("system", "sentinel-system.properties");

        //循环添加
        Properties properties = new Properties();
        for (String profile : sentinelScope) {
            String path = pathMap.get(profile);
            if (!StringUtils.isEmpty(path)) {
                //从classpath路径下面查找文件
                Resource resource = new ClassPathResource(path);
                //加载成PropertySource对象，并添加到Environment环境中
                environment.getPropertySources().addLast(loadProfiles(properties, resource));
            }
        }
    }

    //加载单个配置文件
    private PropertySource<?> loadProfiles(Properties properties, Resource resource) {
        if (null == resource) {
            throw new NullPointerException("资源空指针异常");
        }
        if (!resource.exists()) {
            throw new IllegalArgumentException("资源" + resource + "不存在");
        }
        if (StringUtils.isEmpty(resource.getFilename())) {
            throw new IllegalArgumentException("资源名称" + resource + "不存在");
        }
        try {
            properties.load(resource.getInputStream());
            return new PropertiesPropertySource(resource.getFilename(), properties);
        } catch (IOException ex) {
            throw new IllegalStateException("加载配置文件失败" + resource, ex);
        }
    }

    private Properties loadProperties(File f) throws IOException {
        FileSystemResource resource = new FileSystemResource(f);
        return PropertiesLoaderUtils.loadProperties(resource);
    }
}
